import socket
import os
import sys
import struct


def socket_service_image():
	try:
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		s.bind(('192.168.111.52', 6000))
		s.listen(10)
	
	except socket.error as msg:
		print(msg)
		sys.exit(1)
	print("等待连接.....................")
	while True:
		sock, address = s.accept()  # addr是一个元组(ip,port)
		deal_image(sock, address)


def deal_image(sock, address):
	print(f"接收到来自 {address} 的连接")  # 查看发送端的ip和端口
	while True:
		fileinfo_size = struct.calcsize('128sq')  # 返回格式字符串fmt描述的结构的字节大小
		# print('文件结构的字节大小是', fileinfo_size)
		buf = sock.recv(fileinfo_size)  # 接收图片名
		# print('buf(缓冲区) 是 ', buf)
		if buf:  # 如果接收到了数据就开始接下来的操作
			filename, filesize = struct.unpack('128sq', buf)  # 按照客户端打包的格式进行解包，得到图片的名字和图片大小
			print('文件名称 :', filename.decode())
			# fn = filename.decode().strip('\x00')  # 其实，这里的filename已经是解码完毕去掉字节符号的样子了，我感觉这一步是多此一举
			fn = filename.strip(str.encode('\00'))
			# print('bytes后的文件名称 ', fn)
			new_filename = os.path.join(str.encode('./ou/'), str.encode('new_') + fn)
			print(f'文件新名称为 {new_filename.decode("utf-8")}, 文件大小是 {round(filesize / 1024, 2)}KB')
			
			# 在服务器端新建图片名(可以不用新建的，直接用原来的也行，只要客户端和服务器不是同一个系统或接收到的图片和原图片不在一个文件夹下)
			
			recvd_size = 0
			fp = open(new_filename, 'wb')  # 二进制打开文件
			
			while not recvd_size == filesize:  # 如果收到的直接总数不等于这个文件的直接总数，那么就继续接受数据
				if filesize - recvd_size > 1024:  # 这个最后一次如果数据比
					data = sock.recv(1024)  # 每次从客户端接受1024个字节
					recvd_size += len(data)  # 每次都记录好收到的字节数，然后叠加上去
				
				else:  # 这个最后一次数据如果比1024少的话那么这一次读完就OK了，而且这次结束后循环也就结束了
					data = sock.recv(1024)
					recvd_size = filesize
					# print('数据是', data)  # 输出每一次收到的数据
				fp.write(data)  # 写入图片数据，因为每次都是读取到1024个字节，所以每一次读取都需要把得到的字节进行拼凑
			fp.close()
		
		sock.close()
		
		break


if __name__ == '__main__':
	socket_service_image()
